﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Drawing;

namespace MipsPipelineSimulator
{
    class IFStage
    {
        //能否运行
        static public int enableRun = 0;

        static private ManualResetEvent manuaEevent = new ManualResetEvent(false);

        static private Thread ifThread = null;

        static public Point[] position = new Point[25];

        static public Int64 codeCurrentAddress = 0;

        static private Code code;

        static private MainForm mainForm = null;

        static public bool ifOverOrNop = false;

        static  private void ThreadFun()
        {
            IDStage.nopDrawManualEvent.WaitOne();

            if (IDStage.nopNum > 0)
            {
                IDStage.nopNumManualEvent.Set();
                manuaEevent.Set();
                return;
            }

            IDStage.nopNumManualEvent.Set();

            code = RunTimeCode.GetCode(codeCurrentAddress);

            switch(code.codeType)
            {
                case CodeType.OVER:
                    {
                        enableRun = -1;
                        ifOverOrNop = true;
                        break;
                    }
                case CodeType.NOP:
                    {
                        codeCurrentAddress += 4;
                        ifOverOrNop = true;
                        break;
                    }      
                default:
                    {
                        //第一段
                        string text1 = CommonTool.NumToStr(TypeCode.Int64,codeCurrentAddress,"D",false);
                        Thread thread1 = CommonTool.StartDrawPathsThread(new DrawPaths(
                            new Animate[1] { 
                                CommonTool.SetAnimate(IFStage.position[18],IFStage.position[19],Direction.LeftToRight,text1,true,mainForm.GetGraphics())
                            },IFStage.mainForm));
                        thread1.Join();
                        thread1 = null;

                        Thread thread2 = CommonTool.StartDrawPathsThread(new DrawPaths(
                            new Animate[2] { 
                                CommonTool.SetAnimate(IFStage.position[19],IFStage.position[20],Direction.LeftToRight,text1,true,mainForm.GetGraphics()),
                                CommonTool.SetAnimate(IFStage.position[21],IFStage.position[22],Direction.LeftToRight,code.codeType.ToString(),true,mainForm.GetGraphics())
                            }, IFStage.mainForm));

                        Thread thread3 = CommonTool.StartDrawPathsThread(new DrawPaths(
                           new Animate[2] { 
                                CommonTool.SetAnimate(IFStage.position[19],IFStage.position[14],Direction.BottomToTop,text1,true,mainForm.GetGraphics()),
                                CommonTool.SetAnimate(IFStage.position[14],IFStage.position[15],Direction.LeftToRight,text1,true,mainForm.GetGraphics())
                            }, IFStage.mainForm));

                        Thread thread4 = CommonTool.StartDrawPathsThread(new DrawPaths(
                          new Animate[1] { 
                                CommonTool.SetAnimate(IFStage.position[4],IFStage.position[5],Direction.LeftToRight,"4",true,mainForm.GetGraphics())
                            }, IFStage.mainForm));

                        thread3.Join();
                        thread4.Join();
                        thread3 = null;
                        thread4 = null;

                        string text2 = CommonTool.NumToStr(TypeCode.Int64, codeCurrentAddress + 4, "D", false);

                        //判断前面的指令是否为跳转指令
                        if ((IDStage.code.codeType == CodeType.BEQZ  || IDStage.code.codeType == CodeType.BNEZ))
                        {
                            IDStage.bzManualEvent.WaitOne();
                            if(IDStage.bzSuccess) text2 = CommonTool.NumToStr(TypeCode.Int64, IDStage.bzAddress, "D", false);
                        }

                        Thread thread5 = CommonTool.StartDrawPathsThread(new DrawPaths(
                           new Animate[1] { 
                                CommonTool.SetAnimate(IFStage.position[9],IFStage.position[10],Direction.LeftToRight,text2,true,mainForm.GetGraphics())
                            }, IFStage.mainForm));
                        thread5.Join();
                        thread5 = null;

                      

                        Thread thread6 = CommonTool.StartDrawPathsThread(new DrawPaths(
                          new Animate[1] { 
                                CommonTool.SetAnimate(IFStage.position[11],IFStage.position[12],Direction.LeftToRight,text2,true,mainForm.GetGraphics())
                            }, IFStage.mainForm));
                        thread6.Join();
                        thread6 = null;

                        Thread thread7 = CommonTool.StartDrawPathsThread(new DrawPaths(
                          new Animate[1] { 
                                CommonTool.SetAnimate(IFStage.position[12],IFStage.position[13],Direction.LeftToRight,text2,true,mainForm.GetGraphics())
                            }, IFStage.mainForm));

                        Thread thread8 = CommonTool.StartDrawPathsThread(new DrawPaths(
                          new Animate[4] { 
                                CommonTool.SetAnimate(IFStage.position[12],IFStage.position[3],Direction.BottomToTop,text2,true,mainForm.GetGraphics()),
                                CommonTool.SetAnimate(IFStage.position[3],IFStage.position[2],Direction.RightToLeft,text2,true,mainForm.GetGraphics()),
                                CommonTool.SetAnimate(IFStage.position[2],IFStage.position[16],Direction.TopToBottom,text2,true,mainForm.GetGraphics()),
                                CommonTool.SetAnimate(IFStage.position[16],IFStage.position[17],Direction.LeftToRight,text2,true,mainForm.GetGraphics())
                            }, IFStage.mainForm));

                        thread7.Join();
                        thread7 = null;
                        thread8.Join();
                        thread8 = null;
                        thread2.Join();
                        thread2 = null;

                        //设置PC的值
                        if ((IDStage.code.codeType == CodeType.BEQZ || IDStage.code.codeType == CodeType.BNEZ) && IDStage.bzSuccess) codeCurrentAddress = IDStage.bzAddress;
                        else codeCurrentAddress += 4;

                        Thread thread9 = CommonTool.StartBlinkThread(new Blink(
                            text2, IFStage.position[24], DrawTool.blinkTimes, DrawTool.blinkSpanTime, DrawTool.blinkHideTime, IFStage.mainForm));

                        Thread thread10 = CommonTool.StartBlinkThread(new Blink(
                           code.codeType.ToString(), IFStage.position[23], DrawTool.blinkTimes, DrawTool.blinkSpanTime, DrawTool.blinkHideTime, IFStage.mainForm));

                        thread9.Join();
                        thread9 = null;
                        thread10.Join();
                        thread10 = null;

                        CommonTool.DrawPath(IFStage.mainForm,
                            new DrawPath[7]{
                                 new DrawPath(mainForm.GetGraphics(),new Point[2]{IFStage.position[18],IFStage.position[20]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[2]{IFStage.position[21],IFStage.position[22]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[3]{IFStage.position[19],IFStage.position[14],IFStage.position[15]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[2]{IFStage.position[4],IFStage.position[5]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[2]{IFStage.position[9],IFStage.position[10]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[2]{IFStage.position[11],IFStage.position[13]},DrawTool.orignalPen),
                                 new DrawPath(mainForm.GetGraphics(),new Point[5]{IFStage.position[12],IFStage.position[3],IFStage.position[2],IFStage.position[16],IFStage.position[17]},DrawTool.orignalPen),
                            });

                        IDStage.Wait();
                        if ((IDStage.code.codeType == CodeType.BEQZ || IDStage.code.codeType == CodeType.BNEZ) && IDStage.bzSuccess) IDStage.code = new Code(CodeType.NOP, null);
                        else IDStage.code = IFStage.code;
                        IDStage.args = new object[1] {codeCurrentAddress};
                        IDStage.enableRun++;
                        break;
                    } 
            }
            manuaEevent.Set();
        }

        static public void Start(MainForm param)
        {
            mainForm = param;
            //开始标志
            manuaEevent.Reset();
            IDStage.nopNumManualEvent.Reset();
            IDStage.nopDrawManualEvent.Reset();
            IDStage.bzManualEvent.Reset();
            ifOverOrNop = false;
            ifThread = new Thread(new ThreadStart(ThreadFun));
            ifThread.Start();
        }

        static public void Initialize()
        {
            IFStage.enableRun = 0;
            IFStage.codeCurrentAddress = RunTimeCode.CodeStartAddress;
            manuaEevent = new ManualResetEvent(false);
        }

        static public void Wait()
        {
            manuaEevent.WaitOne();
        }

        static public void Close()
        {
            if (ifThread != null && ifThread.IsAlive)
            {
                ifThread.Join();
            }
        }
    }
}
